/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

using System;
using System.Collections.Generic;

namespace FaceCat {
    /// <summary>
    /// 点击菜单事件
    /// </summary>
    /// <param name="sender">发送者</param>
    /// <param name="item">菜单项</param>
    /// <param name="touchInfo">触摸信息</param>
    public interface FCMenuItemTouchEventCallBack {
        /// <summary>
        /// 点击菜单事件
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="item"></param>
        /// <param name="touchInfo"></param>
        /// <param name="invoke"></param>
        void callMenuItemTouchEvent(String eventName, Object sender, FCMenuItem item, FCTouchInfo touchInfo, Object invoke);
    }

    /// <summary>
    /// 菜单视图
    /// </summary>
    public class FCMenu : FCLayoutDiv {
        /// <summary>
        /// 创建视图
        /// </summary>
        public FCMenu() {
            setAutoSize(true);
            setLayoutStyle(FCLayoutStyle.TopToBottom);
            setMaximumSize(new FCSize(2000, 500));
            setShowHScrollBar(true);
            setShowVScrollBar(true);
            setTopMost(true);
            m_size = new FCSize(200, 200);
        }

        /// <summary>
        /// 菜单项
        /// </summary>
        public ArrayList<FCMenuItem> m_items = new ArrayList<FCMenuItem>();

        /// <summary>
        /// 秒表编号
        /// </summary>
        private int m_timerID = getNewTimerID();

        public bool m_autoHide = true;

        /// <summary>
        /// 设置是否自动隐藏
        /// </summary>
        public virtual void setAutohHide(bool autoHide)
        {
            m_autoHide = autoHide;
        }

        public FCMenuItem m_parentItem;

        /// <summary>
        /// 获取父菜单项
        /// </summary>
        public virtual FCMenuItem getParentItem()
        {
            return m_parentItem;
        }

        /// <summary>
        /// 设置父菜单项
        /// </summary>
        public virtual void setParentItem(FCMenuItem value)
        {
            m_parentItem = value;
        }

        public bool m_popup;

        /// <summary>
        /// 获取是否弹出
        /// </summary>
        public virtual bool canPopup()
        {
            return m_popup;
        }

        /// <summary>
        /// 设置是否弹出
        /// </summary>
        public virtual void setPopup(bool value)
        {
            m_popup = value;
            if (m_popup)
            {
                setVisible(false);
            }
        }

        /// <summary>
        /// 添加项
        /// </summary>
        /// <param name="item">菜单项</param>
        public virtual void addItem(FCMenuItem item) {
            item.setParentMenu(this);
            item.onAddingItem(-1);
            m_items.add(item);
        }

        /// <summary>
        /// 自动适应位置和大小
        /// </summary>
        /// <param name="menu">菜单</param>
        public virtual void adjust(FCMenu menu) {
            FCNative native = getNative();
            if (autoSize()) {
                int contentHeight = menu.getContentHeight();
                int maximumHeight = getMaximumSize().cy;
                menu.setHeight(Math.Min(contentHeight, maximumHeight));
            }
            FCPoint mPoint = menu.getLocation();
            FCSize mSize = menu.getSize();
            FCSize nSize = native.getSize();
            if (mPoint.x < 0) {
                mPoint.x = 0;
            }
            if (mPoint.y < 0) {
                mPoint.y = 0;
            }
            if (mPoint.x + mSize.cx > nSize.cx) {
                mPoint.x = nSize.cx - mSize.cx;
            }
            if (mPoint.y + mSize.cy > nSize.cy) {
                mPoint.y = nSize.cy - mSize.cy;
            }
            menu.setLocation(mPoint);
            menu.update();
        }

        /// <summary>
        /// 调用菜单的触摸事件
        /// </summary>
        /// <param name="eventName">事件ID</param>
        /// <param name="item">菜单项</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void callMenuItemTouchEvent(String eventName, FCMenuItem item, FCTouchInfo touchInfo) {
            if (m_atrEx != null && m_atrEx.m_events != null && m_atrEx.m_events.containsKey(eventName))
            {
                ArrayList<Object> events = m_atrEx.m_events.get(eventName);
                ArrayList<Object> invokes = m_atrEx.m_invokes[eventName];
                int eventSize = events.size();
                for (int i = 0; i < eventSize; i++) {
                    FCMenuItemTouchEventCallBack func = events.get(i) as FCMenuItemTouchEventCallBack;
                    if (func != null) {
                        func.callMenuItemTouchEvent(eventName, this, item, touchInfo, invokes.get(i));
                    }
                }
            }
        }

        /// <summary>
        /// 检查图层是否具有焦点
        /// </summary>
        /// <param name="items">视图集合</param>
        /// <returns>是否有焦点</returns>
        public virtual bool checkDivFocused(ArrayList<FCMenuItem> items) {
            int itemSize = items.size();
            for (int i = 0; i < items.size(); i++) {
                FCMenuItem item = items.get(i);
                FCMenu dropDownMenu = item.getDropDownMenu();
                if (dropDownMenu != null) {
                    if (checkFocused(dropDownMenu)) {
                        return true;
                    }
                }
                ArrayList<FCMenuItem> subItems = item.getItems();
                bool focused = checkDivFocused(subItems);
                if (focused) {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 检查焦点
        /// </summary>
        /// <param name="view">视图</param>
        /// <returns>是否有焦点</returns>
        public virtual bool checkFocused(FCView view) {
            if (view.isFocused()) {
                return true;
            }
            else {
                ArrayList<FCView> subViews = view.getViews();
                if (subViews != null && subViews.size() > 0) {
                    int subViewsSize = subViews.size();
                    for (int i = 0; i < subViewsSize; i++) {
                        bool focused = checkFocused(subViews.get(i));
                        if (focused) {
                            return true;
                        }
                    }
                }
                return false;
            }
        }

        /// <summary>
        /// 清除所有的项
        /// </summary>
        public virtual void clearItems() {
            ArrayList<FCMenuItem> itemsCopy = new ArrayList<FCMenuItem>();
            int itemSize = m_items.size();
            for (int i = 0; i < itemSize; i++) {
                itemsCopy.add(m_items.get(i));
            }
            int copySize = itemsCopy.size();
            for (int i = 0; i < copySize; i++) {
                itemsCopy.get(i).onRemovingItem();
                itemsCopy.get(i).delete();
            }
            m_items.clear();
        }

        /// <summary>
        /// 关闭网格视图
        /// </summary>
        /// <param name="items">菜单集合</param>
        /// <returns>是否关闭成功</returns>
        public virtual bool closeMenus(ArrayList<FCMenuItem> items) {
            int itemSize = items.size();
            bool close = false;
            for (int i = 0; i < itemSize; i++) {
                FCMenuItem item = items.get(i);
                ArrayList<FCMenuItem> subItems = item.getItems();
                if (closeMenus(subItems)) {
                    close = true;
                }
                FCMenu dropDownMenu = item.getDropDownMenu();
                if (dropDownMenu != null && dropDownMenu.isVisible()) {
                    dropDownMenu.m_visible = false;
                    close = true;
                }
            }
            return close;
        }

        /// <summary>
        /// 创建菜单
        /// </summary>
        /// <returns>布局视图</returns>
        public virtual FCMenu createDropDownMenu() {
            FCMenu menu = new FCMenu();
            menu.setPopup(true);
            menu.setShowHScrollBar(true);
            menu.setShowVScrollBar(true);
            return menu;
        }

        /// <summary>
        /// 销毁方法
        /// </summary>
        public override void delete() {
            if (!isDeleted()) {
                stopTimer(m_timerID);
                clearItems();
            }
            base.delete();
        }

        /// <summary>
        /// 获取视图类型
        /// </summary>
        /// <returns>视图类型</returns>
        public override String getViewType() {
            return "Menu";
        }

        /// <summary>
        /// 获取事件名称列表
        /// </summary>
        /// <returns>名称列表</returns>
        public override ArrayList<String> getEventNames() {
            ArrayList<String> eventNames = base.getEventNames();
            eventNames.AddRange(new String[] { "MenuItemClick" });
            return eventNames;
        }

        /// <summary>
        /// 获取所有的菜单项
        /// </summary>
        /// <returns></returns>
        public virtual ArrayList<FCMenuItem> getItems() {
            return m_items;
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">返回属性值</param>
        /// <param name="type">返回属性类型</param>
        public override void getAttribute(String name, ref String value, ref String type) {
            if (name == "popup") {
                type = "bool";
                value = FCTran.boolToStr(canPopup());
            }
            else {
                base.getAttribute(name, ref value, ref type);
            }
        }

        /// <summary>
        /// 获取属性名称列表
        /// </summary>
        /// <returns>属性名称列表</returns>
        public override ArrayList<String> getAttributeNames() {
            ArrayList<String> attributeNames = base.getAttributeNames();
            attributeNames.AddRange(new String[] { "Popup" });
            return attributeNames;
        }

        /// <summary>
        /// 插入项
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="item">菜单项</param>
        public virtual void insertItem(int index, FCMenuItem item) {
            item.setParentMenu(this);
            item.onAddingItem(index);
            m_items.Insert(index, item);
        }

        /// <summary>
        /// 是否不处理自动隐藏
        /// </summary>
        /// <returns>是否不处理</returns>
        public virtual bool onAutoHide() {
            return true;
        }

        /// <summary>
        /// 菜单点击方法
        /// </summary>
        /// <param name="item">菜单项</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void onMenuItemClick(FCMenuItem item, FCTouchInfo touchInfo) {
            if (item.getItems().size() == 0) {
                callMenuItemTouchEvent("onmenuitemclick", item, touchInfo);
                bool close = closeMenus(m_items);
                if (m_popup) {
                    hide();
                }
                else {
                    getNative().invalidate();
                }
            }
            else {
                onMenuItemTouchMove(item, touchInfo);
            }
        }

        /// <summary>
        /// 菜单触摸移动方法
        /// </summary>
        /// <param name="item">菜单项</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void onMenuItemTouchMove(FCMenuItem item, FCTouchInfo touchInfo) {
            FCNative native = getNative();
            ArrayList<FCMenuItem> items = null;
            FCMenuItem parentItem = item.getParentItem();
            if (parentItem != null) {
                items = parentItem.getItems();
            }
            else {
                items = m_items;
            }
            //关闭其他表格
            bool close = closeMenus(items);
            if (item.getItems().size() > 0) {
                FCMenu dropDownMenu = item.getDropDownMenu();
                //获取位置和大小
                if (dropDownMenu != null && !dropDownMenu.isVisible()) {
                    dropDownMenu.setNative(native);
                    FCLayoutStyle layoutStyle = getLayoutStyle();
                    FCPoint location = new FCPoint(native.clientX(item) + item.getWidth(), native.clientY(item));
                    if (layoutStyle == FCLayoutStyle.LeftToRight || layoutStyle == FCLayoutStyle.RightToLeft) {
                        location.x = native.clientX(item);
                        location.y = native.clientY(item) + item.getHeight();
                    }
                    //设置弹出位置
                    dropDownMenu.setOpacity(getOpacity());
                    dropDownMenu.setLocation(location);
                    dropDownMenu.bringToFront();
                    dropDownMenu.focus();
                    dropDownMenu.show();
                    adjust(dropDownMenu);
                    native.invalidate();
                    return;
                }
            }
            if (close)
            {
                native.invalidate();
            }
        }

        /// <summary>
        /// 触摸点击方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchDown(FCTouchInfo touchInfo) {
            base.onTouchDown(touchInfo);
            bool close = closeMenus(m_items);
            getNative().invalidate();
        }

        /// <summary>
        /// 秒表方法
        /// </summary>
        /// <param name="timerID">秒表ID</param>
        public override void onTimer(int timerID) {
            base.onTimer(timerID);
            if (m_timerID == timerID) {
                if (m_autoHide && m_parentItem == null && isVisible()) {
                    if (!checkFocused(this) && !checkDivFocused(m_items) && onAutoHide()) {
                        bool close = closeMenus(m_items);
                        if (m_popup) {
                            hide();
                        }
                        else {
                            getNative().invalidate();
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 可见状态改变方法
        /// </summary>
        public override void onVisibleChanged() {
            base.onVisibleChanged();
            if (isVisible()) {
                if (m_popup) {
                    FCHScrollBar hScrollBar = getHScrollBar();
                    FCVScrollBar vScrollBar = getVScrollBar();
                    if (hScrollBar != null) {
                        hScrollBar.setPos(0);
                    }
                    if (vScrollBar != null) {
                        vScrollBar.setPos(0);
                    }
                    focus();
                    //修正显示位置
                    adjust(this);
                }
                startTimer(m_timerID, 10);
            }
            else {
                stopTimer(m_timerID);
                bool close = closeMenus(m_items);
                FCNative native = getNative();
                if (native != null) {
                    native.invalidate();
                }
            }
        }

        /// <summary>
        /// 移除菜单项
        /// </summary>
        /// <param name="item">菜单项</param>
        public virtual void removeItem(FCMenuItem item) {
            item.onRemovingItem();
            m_items.remove(item);
        }

        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="name">属性名</param>
        /// <param name="value">属性值</param>
        public override void setAttribute(String name, String value) {
            if (name == "popup") {
                setPopup(FCTran.strToBool(value));
            }
            else {
                base.setAttribute(name, value);
            }
        }
    }
}
